﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using Microsoft.Practices.ServiceLocation;
using System.Windows;
using System.ComponentModel.Composition;
using System.Reflection;

namespace Dynamic_UI_Framework
{
    public class Region : IRegion
    {
        public IVisual CurrentItem
        {
            get { return currentItem; }
            set
            {
                currentItem = value;
                RaiseCurrentItemChanged();
            }
        }
        IVisual currentItem;

        public string Name
        {
            get;
            set;
        }

        public IVisual Owner
        {
            get;
            set;
        }

        public void Activate(IVisual v)
        {
            if (Owner != null)
                Owner.Activate(this);
        }

        public System.Windows.FrameworkElement Target
        {
            get;
            set;
        }

        public List<MenuItem> GetMenuItem()
        {
            List<MenuItem> list = new List<MenuItem>();
            var mapping = ServiceLocator.Current.GetInstance<PanelAdapterMapping>();
            foreach (var item in mapping.Mappings)
            {
                MenuItem mi = new MenuItem();
                mi.Header = item.Key.Name;
                mi.Tag = item.Value;
                mi.Click += (s, e) =>
                    {
                        var adapter = mi.Tag as IAdapter;
                        IVisual v = adapter.DefaultBuild(mi.Header.ToString());
                        v.Owner = this;
                        this.CurrentItem = v;
                    };
                list.Add(mi);
            }
            return list;
        }

        void RaiseCurrentItemChanged()
        {
            var hander = CurrentItemChanged;
            if (hander != null)
                hander(this, null);

            UIContext.RaiseVisualModified(this);
        }

        public event EventHandler CurrentItemChanged;
    }

    [Export("Region", typeof(IBuilder))]
    public class RegionBuilder : IBuilder
    {
        public UINode GetUINode(IVisual obj)
        {
            Region region = obj as Region;
            if (region == null)
                return null;

            UINode node = new UINode();
            node.Target = region;
            node.TypeName = region.GetType().Name;
            node.Name = region.Name;
            node.Properties.Add("target", region.Target.GetType().FullName);

            if (region.CurrentItem != null)
            {
                string key = region.CurrentItem.GetType().Name;
                IBuilder builder = ServiceLocator.Current.GetInstance<IBuilder>(key);
                if (builder == null)
                    throw new Exception("builder == null");

                UINode child = builder.GetUINode(region.CurrentItem);
                child.Owner = node;
                node.Children.Add(child);
            }
            return node;
        }
        public IVisual Build(UINode node)
        {
            string target = node.Properties.ContainsKey("target") ? node.Properties["target"].ToString() : null;
            if(string.IsNullOrEmpty(target))
                throw new Exception("string.IsNullOrEmpty(typeFullName)");

            RegionAdapterMapping mapping = ServiceLocator.Current.GetInstance<RegionAdapterMapping>();
            IAdapter adapter = mapping.GetMappingByTypeFullName(target);
            if(adapter == null)
                throw new Exception("adapter == null");

            Region region = adapter.DefaultBuild(node.Name) as Region;
            foreach (var item in node.Children)
            {
                IBuilder builder = ServiceLocator.Current.GetInstance<IBuilder>(item.TypeName);
                IVisual child = builder.Build(item) as IVisual;
                child.Owner = region;
                region.CurrentItem = child;
            }
            return region;
        }
    }
}
